#pragma once
#include "CeBrainCommon.h"

class CNervus;
class CNervusAntenna
{
public:
	CNervusAntenna(CNervus* pNervus, int Delay)
		:m_nDelay(Delay), m_pNervus(pNervus), m_pNervusAntennaPeer(NULL)
	{
		m_nSignalBuffer = new Complex[Delay+1];
		m_nCurrentReadPos = 0;

		//memset( m_nSignalBuffer, 0, sizeof(int)*(Delay+1) );
		
		Complex CONST_C0;
		for( int i=0; i<Delay+1; i++ )
			m_nSignalBuffer[i] = c0;
	};
	CNervusAntenna(void)
		:m_nDelay(0), m_pNervus(NULL), m_pNervusAntennaPeer(NULL)
	{
		m_nSignalBuffer = new Complex[1];
		m_nCurrentReadPos = 0;

		//memset( m_nSignalBuffer, 0, sizeof(int)*(1) );
		Complex CONST_C0;
		m_nSignalBuffer[0] = c0;
	};
	~CNervusAntenna(void){delete m_nSignalBuffer; };

	void Connect( CNervusAntenna* pNervusAntenna )
	{
		SetPeer( pNervusAntenna );
		pNervusAntenna->SetPeer( this );
	};

	void SetPeer( CNervusAntenna* pNervusAntenna )
	{
		m_pNervusAntennaPeer = pNervusAntenna;
	};

	CNervusAntenna* GetPeer( )
	{
		return m_pNervusAntennaPeer;
	};

	bool BreakCurrentConnection( void )
	{
		if( !GetPeer() )
			return false;
		else
		{
			GetPeer()->SetPeer( NULL );
			SetPeer( NULL );
			return true;
		}
	};

	void SetSignal( Complex nSignal )
	{
		int nCurrentWritePos = (m_nCurrentReadPos+m_nDelay) % (m_nDelay+1);
		//if(m_nDelay>0)TRACE(" {%d}nCurrentWritePos=%d\n",m_nDelay,nCurrentWritePos);
		m_nSignalBuffer[ nCurrentWritePos ] = nSignal;
	};

	Complex GetSignal( void )
	{//if(m_nDelay>0)TRACE(" {%d}m_nCurrentReadPos=%d\n",m_nDelay,m_nCurrentReadPos);
		Complex nSignal = m_nSignalBuffer[ m_nCurrentReadPos++ ];
		if( m_nCurrentReadPos > m_nDelay )
			m_nCurrentReadPos = 0;
		return nSignal;
	};

	Complex ReadCurrentSignal( void )
	{
		return m_nSignalBuffer[ m_nCurrentReadPos ];
	};

	CNervus* GetMyNervus( void )
	{
		return m_pNervus;
	};

	bool IsNotConnected( void )
	{
		return GetPeer() ? false : true;
	};

	void TransmitSignal( void )
	{
		if( GetPeer() )
			GetPeer()->SetSignal( GetSignal() );
	};

private:
	int m_nDelay;
	CNervusAntenna* m_pNervusAntennaPeer;
	CNervus* m_pNervus;
	Complex *m_nSignalBuffer;
	int m_nCurrentReadPos;
	//int m_nCurrentWritePos;
};

typedef struct _NervusPOS{
int nColumn;
int nRow;
} NervusPOS;

typedef struct _NervusValue{
	NervusPOS pos;
	double value_real;
	double value_image;
} NervusValue;

class CNervus
{
public:
	CNervus(void);
	virtual ~CNervus(void);

	//virtual int GetExcitedOutput( void ) = NULL;
	void ProcessSignal( void );
	void DoSignalTransmition( void );

	void SetPosition( NervusPOS pos )
	{
		m_Pos = pos;
	};
	NervusPOS GetPosition( void )
	{
		return m_Pos; 
	};

	CNervus* GetOutputLinkedNervus( int nOutputIndex )
	{
		if( m_pOutputNervusAntenna[nOutputIndex]->GetPeer() )
		{
			return m_pOutputNervusAntenna[nOutputIndex]->GetPeer()->GetMyNervus();
		}
		else
			return NULL;
	}

	void Connect( int nOutputIndex, CNervusAntenna* pTargetNervusAntenna )
	{
		if( !m_pOutputNervusAntenna[nOutputIndex]->IsNotConnected() )
		{
			m_pOutputNervusAntenna[nOutputIndex]->BreakCurrentConnection();
		}
		m_pOutputNervusAntenna[nOutputIndex]->Connect( pTargetNervusAntenna );
	};

	bool ConnectNervus( int nOutputIndex, CNervus* pTargetNervus )
	{
		if( pTargetNervus->FindEmptyInputAntennna() )
		{
			if( !m_pOutputNervusAntenna[nOutputIndex]->IsNotConnected() )
			{
				m_pOutputNervusAntenna[nOutputIndex]->BreakCurrentConnection();
			}
			m_pOutputNervusAntenna[nOutputIndex]->Connect( pTargetNervus->FindEmptyInputAntennna() );
			return true;
		}
		else
			return false;
	};

	CNervusAntenna* FindEmptyInputAntennna( void )
	{
		for( int i=0; i<NERVUS_ANTENNA_NUM; i++ )
			if( m_pInputNervusAntenna[i]->IsNotConnected() )
				return m_pInputNervusAntenna[i];
		return NULL;
	};

	bool CutConnection( int nOutputIndex )
	{
		return m_pOutputNervusAntenna[nOutputIndex]->BreakCurrentConnection();
	};

	void SetValue( double real, double image )
	{
		m_cValue.real = real;
		m_cValue.image = image;
	};

	Complex GetValue( void )
	{
		return m_cValue;
	};

private:
	CNervusAntenna *m_pInputNervusAntenna[NERVUS_ANTENNA_NUM];
	CNervusAntenna *m_pOutputNervusAntenna[NERVUS_ANTENNA_NUM];
	NervusPOS m_Pos;
	//bool m_bNoResponseStatus;
	//int m_nExcitedCount;
	//int m_nSignalCount;
	Complex m_cValue;
};
/*
class CPositiveNervus : public CNervus
{
public:
	CPositiveNervus(void) : CNervus(){};
	~CPositiveNervus(void){};

	virtual int GetExcitedOutput( void )
	{
		return 1;
	};
};

class CNegativeNervus : public CNervus
{
public:
	CNegativeNervus(void) : CNervus(){};
	~CNegativeNervus(void){};

	virtual int GetExcitedOutput( void )
	{
		return -1;
	};
};
*/